package cn.wh.ymcc.mq.consumer;

import cn.wh.ymcc.domain.PayOrder;
import cn.wh.ymcc.dto.PayDto;
import cn.wh.ymcc.service.IPayOrderService;
import cn.wh.ymcc.util.AssertUtil;
import com.alibaba.fastjson.JSONObject;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.MessageModel;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.Date;

/**
 * 课程订单到支付订单的消费者
 * 一个消息只能生成一个支付单,所以只能被一个消费者消费
 * 那么消费者只能使用 集群模式---默认可以不写
 * (注意:如果一个消息要被多个消费者消费的话,那么请使用广播模式)
 */
@Component
@RocketMQMessageListener(
        consumerGroup = "course-order-pay-consumer",
        topic = "course-order-topic",
        selectorExpression = "course-order-tag"
        //messageModel = MessageModel.CLUSTERING  集群模式
)
public class CourseOrder2PayOrderConsumer implements RocketMQListener<MessageExt> {

    @Autowired
    private IPayOrderService payOrderService;
    //消费消息
    /**
     * (重点)必须保证消费方消息的幂等性
     * 1.拿到消息保证消息不为空
     * 2.根据拿到的订单号,查询pay-order表,校验订单号对应的支付单是否存在
     *  2.1有,说明已经消费过了,直接签收--后面mq就不会在推送此消息了
     *  2.2没有,说明是第一次消费这个消息,保存支付单,pay-order
     *
     *  扩展: 作为rocketMq,消费方是否签收消息是通过是否有异常来判断额
     *  OnMessage方法体:
     *   1.如果有异常,签收失败--此消息会滞留在Mq中,下次还会再被消费 直到mq自动清理
     *   2.没有异常,签收成功 -- 消息不会被再次消费
     * @param messageExt
     */
    @Override
    public void onMessage(MessageExt messageExt) {
        //byte数组转成JSON格式
        byte[] body = messageExt.getBody();
        AssertUtil.isNotNull(body,"消息体为空!!");
        String jsonStr = new String(body, StandardCharsets.UTF_8);
        PayDto payDto = JSONObject.parseObject(jsonStr, PayDto.class);
        //根据拿到的订单号,查询pay-order表,校验订单号对应的支付单是否存在
        PayOrder payOrder = payOrderService.selectByOrderNumber(payDto.getOrderNo());
        if (payOrder != null){
            return;
        }
        payOrder = new PayOrder();
        //拷贝
        BeanUtils.copyProperties(payDto,payOrder);
        payOrder.setCreateTime(new Date());
        payOrder.setPayStatus(0);
        payOrderService.insert(payOrder);
    }
}
